<template>
  <!-- 地图 -->
  <div id="map">
    <div class="do-postion" v-if="position">
      <a-button type="primary" @click="doPostion" icon="compass" shape="circle"></a-button>
    </div>
    <div class="right" v-if="readyStatus">
      <Point
        v-if="clickFlag == 'point'"
        ref="point"
        :location="location"
        @getPoint="getPoint"
      />
      <Area
        v-if="clickFlag == 'area'"
        ref="area"
        :locations="locations"
        :height="height"
        @getPoint="getPoint"
      />
      <Fence
        v-if="clickFlag == 'fence'"
        ref="fence"
        :locations="locations"
        :height="height"
        @getPoint="getPoint"
      />
      <Lines
        v-if="clickFlag == 'lines'"
        ref="lines"
        :locations="locations"
        @getPoint="getPoint"
      />
    </div>
    <vc-viewer
      ref="viewer"
      :logo="false"
      :selectionIndicator="false"
      :infoBox="false"
      :animation="false"
      :timeline="false"
      :shouldAnimate="false"
      @ready="ready"
      @LEFT_CLICK="LEFT_CLICK"
    >
      <!-- 天地影像图-->
      <vc-layer-imagery ref="layerText">
        <vc-provider-imagery-tianditu
          :mapStyle="mapStyle"
          :protocol="protocol"
          token="436ce7e50d27eede2f2929307e6b33c0"
        ></vc-provider-imagery-tianditu>
      </vc-layer-imagery>
    </vc-viewer>
  </div>
</template>
<script>
  import Point from './point.vue'
  import Area from './area.vue'
  import Fence from './fence.vue'
  import Lines from './lines.vue'

  export default {
  components: {
    Point,
    Area,
    Fence,
    Lines
  },
  data() {
    return {
      mapStyle: 'img_w', // 天地影像图类型
      protocol: 'http', // 天地图请求协议类型
      cesiumInstance: null,
      cameraLocation: {}, //厂区位置地图数据
      entities: {
        model: [], // 三维模型地图覆盖物
        location: [], //厂区位置地图数据
      },
      outerNgitudeAndLatitude: [], //外圈坐标系
      internalLoopNgitudeAndLatitude: [], //内圈坐标系
      readyStatus: false, //地图加载完毕
    }
  },
  props: {
    clickFlag: {
      type: String,
      default: '',
    },
    position: {
      type: Boolean,
      default: true,
    },
    //关闭功能
    diabled: {
      type: Boolean,
      default: false,
    },
    model: {
      type: Object,
      default: () => {},
    },
    location: {
      type: Object,
      default: () => {},
    },
    locations: {
      type: Array,
      default: () => [],
    },
    height: {
      type: [Number, String],
      default: '',
    },
  },
  methods: {
    ready(cesiumInstance) {
      // gis准备成功事件
      console.log('ready')
      window.cesiumInstance = cesiumInstance
      const { Cesium, viewer } = cesiumInstance
      viewer.scene.requestRenderMode = true;
      this.$emit('ready')
    },
    //清楚所有模型以及实例模型数据
    reset() {
      const { Cesium, viewer } = window.cesiumInstance
      viewer.scene.primitives.removeAll()
      viewer.entities.removeAll()
    },
    showModel() {
      const _this = this
      //清空地图模型数据
      this.hideModel()
      const { Cesium, viewer } = window.cesiumInstance
      this.entities['location'].map((item, index) => {
        if (item.url) {
          let tileset = viewer.scene.primitives.add(
            new Cesium.Cesium3DTileset({
              url: item.url,
            })
          )
          tileset.tilesetFlag = 'tilesetModel' // 给所有模型增加标记，方便显示、隐藏操作
          tileset.readyPromise.then(function (tileset) {
            // 获取模型中心点坐标信息
            let cartographic = Cesium.Cartographic.fromCartesian(tileset.boundingSphere.center)

            // 将坐标信息转换成经纬度和高度
            let lng = Cesium.Math.toDegrees(cartographic.longitude)
            let lat = Cesium.Math.toDegrees(cartographic.latitude)
            let height = cartographic.height

            // 模型原始坐标信息
            let surface = Cesium.Cartesian3.fromRadians(Cesium.Math.toRadians(lng), Cesium.Math.toRadians(lat), height)
            // 模型位置修改后的坐标信息，可在此填入自定义的坐标信息
            let offset = Cesium.Cartesian3.fromRadians(
              Cesium.Math.toRadians(item.longitude),
              Cesium.Math.toRadians(item.latitude),
              item.high
            )

            // 计算两个坐标信息的差距
            let translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3())
            // 将偏差应用至模型中，来改变模型位置
            tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation)
          })
          _this.entities['model'].push(tileset)
        }
      })
      //将模型的高度部署到功能上
      _this.readyStatus = true
    },
    //隐藏3d模型
    hideModel() {
      const { viewer } = window.cesiumInstance
      if (this.entities.model.length) {
        this.entities.model.map((item, index) => {
          viewer.scene.primitives.remove(item)
        })
        this.entities.model = []
      }
    },
    gotoDefaultPosition(modelSource) {
      const { Cesium, viewer } = window.cesiumInstance
      // 进入页面，将地图定位至默认展示的厂区位置
      //获取当前地图的视觉位置，根据模型里的defaultShow 1/0 字段判断
      const _selectModelSource = modelSource.filter((item) => item.defaultShow == 1)[0]
      let location = _selectModelSource.anglePosition.split(',')
      viewer.camera.flyTo({
        destination: new Cesium.Cartesian3(location[0], location[1], location[2]),
        orientation: {
          heading: _selectModelSource.arcDirection,
          pitch: _selectModelSource.radian,
          roll: _selectModelSource.radianAngle,
        },
      })
      this.cameraLocation = _selectModelSource
      this.entities['location'] = modelSource
      //展示 模型
      this.showModel()
    },
    //定位
    doPostion() {
      const { Cesium, viewer } = window.cesiumInstance
      // 进入页面，将地图定位至默认展示的厂区位置
      if (!this.cameraLocation.anglePosition) return
      let location = this.cameraLocation.anglePosition.split(',')
      viewer.camera.flyTo({
        destination: new Cesium.Cartesian3(location[0], location[1], location[2]),
        orientation: {
          heading: this.cameraLocation.arcDirection,
          pitch: this.cameraLocation.radian,
          roll: this.cameraLocation.radianAngle,
        },
      })
    },
    LEFT_CLICK(movement) {
      this.$refs[this.clickFlag].LEFT_CLICK(movement)
    },
    setModelUrl({ url }) {
      // 设置3D模型
      const { Cesium, viewer } = window.cesiumInstance
      viewer.entities.removeAll()

      let tileset = viewer.scene.primitives.add(
        new Cesium.Cesium3DTileset({
          url: url,
        })
      )
      let that = this
      tileset.readyPromise.then(function (tileset) {
        // 获取模型中心点坐标信息
        let cartographic = Cesium.Cartographic.fromCartesian(tileset.boundingSphere.center)

        // 将坐标信息转换成经纬度和高度
        let lng = Cesium.Math.toDegrees(cartographic.longitude)
        let lat = Cesium.Math.toDegrees(cartographic.latitude)
        let height = cartographic.height
        //数据回调
        that.$emit('setModel', { lng, lat, height })

        // 模型原始坐标信息
        let surface = Cesium.Cartesian3.fromRadians(Cesium.Math.toRadians(lng), Cesium.Math.toRadians(lat), height)
        // 模型位置修改后的坐标信息，可在此填入自定义的坐标信息
        let offset = Cesium.Cartesian3.fromRadians(Cesium.Math.toRadians(lng), Cesium.Math.toRadians(lat), height)

        // 计算两个坐标信息的差距
        let translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3())
        // 将偏差应用至模型中，来改变模型位置
        tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation)
        that.focusToModel(tileset)
      })
    },
    //预览模型
    previewModel(model) {
      // 使用页面数据做预览
      const { Cesium, viewer } = window.cesiumInstance
      viewer.scene.primitives.removeAll()
      if (model.url) {
        // 判断是否填写模型url
        let tileset = viewer.scene.primitives.add(
          new Cesium.Cesium3DTileset({
            url: model.url,
          })
        )
        let that = this
        tileset.readyPromise.then(function (tileset) {
          // 获取模型中心点坐标信息
          let cartographic = Cesium.Cartographic.fromCartesian(tileset.boundingSphere.center)

          // 将坐标信息转换成经纬度和高度
          let lng = Cesium.Math.toDegrees(cartographic.longitude)
          let lat = Cesium.Math.toDegrees(cartographic.latitude)
          let height = cartographic.height

          // 模型原始坐标信息
          let surface = Cesium.Cartesian3.fromRadians(Cesium.Math.toRadians(lng), Cesium.Math.toRadians(lat), height)

          let reg = /^(-?\d+)(\.\d+)?$/
          let offsetLon, offsetLat, offsetHigh // 判断页面是否填写正确的模型位置数据，没有则使用模型原始数据
          console.log(model.longitude,model.latitude,model.high,reg.test(model.longitude),reg.test(model.latitude),reg.test(model.high))
          if (reg.test(model.longitude)) {
            offsetLon = Cesium.Math.toRadians(model.longitude)
          } else {
            offsetLon = Cesium.Math.toRadians(lng)
          }
          if (reg.test(model.latitude)) {
            offsetLat = Cesium.Math.toRadians(model.latitude)
          } else {
            offsetLat = Cesium.Math.toRadians(lat)
          }
          if (reg.test(model.high)) {
            offsetHigh = model.high
          } else {
            offsetHigh = height
          }
          // 模型位置修改后的坐标信息，可在此填入自定义的坐标信息
          let offset = Cesium.Cartesian3.fromRadians(offsetLon, offsetLat, offsetHigh)

          // 计算两个坐标信息的差距
          let translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3())
          // 将偏差应用至模型中，来改变模型位置
          tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation)
          that.focusToModel()
        })
      }
    },
    //聚焦视觉到3d模型
    focusToModel(tileset) {
      // 聚焦视角至3D模型
      const { Cesium, viewer } = window.cesiumInstance
      if (tileset) {
        viewer.flyTo(tileset, {
          duration: 2.0,
          offset: new Cesium.HeadingPitchRange(0, -1.7, tileset.boundingSphere.radius * 2),
        })
      } else {
        let location = this.model.anglePosition.split(',')
        const { arcDirection, radian, radianAngle } = this.model
        viewer.camera.flyTo({
          destination: new Cesium.Cartesian3(location[0], location[1], location[2]),
          orientation: {
            heading: arcDirection,
            pitch: radian,
            roll: radianAngle,
          },
        })
      }
    },
    //获取当前摄像头数据
    getCurrentView() {
      // 获取当前视角的地图数据
      const { Cesium, viewer } = window.cesiumInstance
      const obj = {
        location: viewer.camera.position.x + ',' + viewer.camera.position.y + ',' + viewer.camera.position.z,
        heading: viewer.camera.heading,
        pitch: viewer.camera.pitch,
        roll: viewer.camera.roll,
      }
      return obj
    },
    getPoint(val) {
      this.$emit('getPoint', val)
    },
  },
}
</script>
<style lang="less" scoped>
#map {
  width: 100%;
  height: 100%;
  position: relative;
  z-index: 1;
  background: #000;
  .do-postion {
    position: absolute;
    top: 20px;
    left: 20px;
    z-index: 11;
  }
  .right {
    position: absolute;
    right: 10px;
    top: 10px;
    z-index: 11;
    width: 300px;
    height: auto;
    background: #131c32;
    opacity: 0.8;
    border: 1px solid rgba(2, 224, 247, 0.5);
    padding: 10px;
  }
}
</style>